package com.ryx.service.Impl;

import com.ryx.constants.Constant;
import com.ryx.entity.SysDept;
import com.ryx.entity.SysUser;
import com.ryx.exception.GlobalException;
import com.ryx.exception.code.BaseResponseCode;
import com.ryx.mapper.SysDeptMapper;
import com.ryx.mapper.SysUserMapper;
import com.ryx.service.DeptService;
import com.ryx.service.UserService;
import com.ryx.utils.CodeUtil;
import com.ryx.utils.RedisUtil;
import com.ryx.vo.req.DeptAddReqVo;
import com.ryx.vo.req.DeptUpdateReqVo;
import com.ryx.vo.resp.DeptRespNodeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @BelongsPackage: com.ryx.service.Impl
 * @Author: 容永轩
 * @CreateTime: 2021-01-01
 * @Description:
 */
@Service
@Transactional
@Slf4j
public class DeptServiceImpl  implements DeptService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<SysDept> selectAll() {

        List<SysDept> list = sysDeptMapper.selectAll();

        for (SysDept s: list) {
            SysDept parent = sysDeptMapper.selectByPrimaryKey(s.getPid());
            if(parent!=null){
                s.setPidName(parent.getName());
            }
        }
        return list;
    }

    @Override
    public List<DeptRespNodeVo> deptTreeList(String deptId) {
        //先查出所有部门数据
        List<SysDept> list = sysDeptMapper.selectAll();

        for (SysDept s: list) {
            SysDept parent = sysDeptMapper.selectByPrimaryKey(s.getPid());
            if(parent!=null){
                s.setPidName(parent.getName());
            }
        }

        //要想去掉这个部门的叶子节点，直接在数据源移除这个部门就可以了
        if(!StringUtils.isEmpty(deptId)&&!list.isEmpty()){
            for (SysDept s: list) {
                if(s.getId().equals(deptId)){
                    list.remove(s);
                    break;
                }
            }
        }

        //默认添加一个顶级的部门 ，所有部门的顶级都是默认的
        DeptRespNodeVo respNodeVO=new DeptRespNodeVo();
        respNodeVO.setId("0");
        respNodeVO.setTitle("默认顶级部门");
        //把查出来的数据传入
        respNodeVO.setChildren(getTree(list));
        List<DeptRespNodeVo> result = new ArrayList<>();

        result.add(respNodeVO);


        return result;
    }



    public List<DeptRespNodeVo> getTree(List<SysDept> allDepts){
        List<DeptRespNodeVo> list = new ArrayList<>();

        if (allDepts.isEmpty()){
            return list;
        }
        //遍历传入查出来的数据
        for (SysDept s: allDepts) {
            if(s.getPid().equals("0")){
                //顶级目录 判断是不是0 先组装最上层的数据
                DeptRespNodeVo respNodeVO=new DeptRespNodeVo();
                respNodeVO.setId(s.getId());
                respNodeVO.setTitle(s.getName());
                //继续往下一层遍历
                respNodeVO.setChildren(getChild(s.getId(),allDepts));
                list.add(respNodeVO);
            }
        }
        return list;




    }

    public List<DeptRespNodeVo> getChild(String id,List<SysDept> allDepts){

        List<DeptRespNodeVo> list = new ArrayList<>();

        for (SysDept dept : allDepts) {
            //此时判断父id是不是我们传入的id 如果是那就把它添加到父级下面，不断递归
            if(dept.getPid().equals(id)){
                DeptRespNodeVo deptRespNodeVO=new DeptRespNodeVo();
                deptRespNodeVO.setId(dept.getId());
                deptRespNodeVO.setTitle(dept.getName());
                deptRespNodeVO.setChildren(getChild(dept.getId(),allDepts));
                list.add(deptRespNodeVO);

            }
        }
        return list;
    }



    @Override
    public SysDept addDept(DeptAddReqVo vo) {

        String relationCode;
        long deptCount=redisUtil.incrby(Constant.DEPT_CODE_KEY,1);
        String deptCode= CodeUtil.deptCode(String.valueOf(deptCount),7,"0");
        SysDept parent=sysDeptMapper.selectByPrimaryKey(vo.getPid());
        if(vo.getPid().equals("0")){
            relationCode=deptCode;
        }else if(null==parent){
            log.info("父级数据不存在{}",vo.getPid());
            throw new GlobalException(BaseResponseCode.DATA_ERROR);
        }else {
            relationCode=parent.getRelationCode()+deptCode;
        }
        SysDept sysDept=new SysDept();
        BeanUtils.copyProperties(vo,sysDept);
        sysDept.setId(UUID.randomUUID().toString());
        sysDept.setCreateTime(new Date());
        sysDept.setDeptNo(deptCode);
        sysDept.setRelationCode(relationCode);
        int i = sysDeptMapper.insertSelective(sysDept);
        if(i!=1){
            throw new GlobalException(BaseResponseCode.OPERATION_ERROR);
        }
        return sysDept;
    }


    @Override
    public void updateDept(DeptUpdateReqVo vo) {

        //拿到当前操作的部门实体
        SysDept sysDept = sysDeptMapper.selectByPrimaryKey(vo.getId());
        if (sysDept == null){
            throw new GlobalException(BaseResponseCode.DATA_ERROR);
        }

        //保存更新的部门数据
        SysDept update=new SysDept();
        BeanUtils.copyProperties(vo,update);
        update.setUpdateTime(new Date());

        //更新数据
        int i = sysDeptMapper.updateByPrimaryKeySelective(update);
        if (i !=1){
            throw new GlobalException(BaseResponseCode.DATA_ERROR);
        }


        //维护层级关系  当前操作的部门实体的层级关系
        // 如果当前表单提交的vo的pid和当前操作的部门实体pid一致 就不需要维护
        if(!vo.getPid().equals(sysDept.getPid())){

            //子集的部门层级关系编码=父级部门层级关系编码+它本身部门编码
            //newParent当前提交表单的父级实体
            SysDept newParent=sysDeptMapper.selectByPrimaryKey(vo.getPid());
            if(!vo.getPid().equals("0")&&null==newParent){
                log.info("修改后的部门在数据库查找不到{}",vo.getPid());
                throw new GlobalException(BaseResponseCode.DATA_ERROR);
            }

            //拿到当前操作的部门实体的父级实体
            SysDept oldParent=sysDeptMapper.selectByPrimaryKey(sysDept.getPid());

            String oldRelation;  //旧的层级关系
            String newRelation;  //新的层级关系
            /*
             * 根目录挂靠到其它目录
             */
            if(sysDept.getPid().equals("0")){
                //切换到其他目录 操作的是目录下的某一个
                oldRelation=sysDept.getRelationCode();
                newRelation=newParent.getRelationCode()+sysDept.getDeptNo();
            }else if(vo.getPid().equals("0")){
                //顶级目录为0
                oldRelation=sysDept.getRelationCode();
                newRelation=sysDept.getDeptNo();
            }else {
                //整个目录换到其他目录
                oldRelation=oldParent.getRelationCode();
                newRelation=newParent.getRelationCode();
            }

            //调用dao 更新RelationCode
            //根据当前操作的实体的RelationCode，模糊查询 只要有当前操作实体的关系的 都把oldRelation这一部分替换成newRelation
            sysDeptMapper.updateRelationCode(oldRelation,newRelation,sysDept.getRelationCode());
        }



    }

    @Override
    public void deletedDept(String id) {
        //拿到当前要删除的节点信息
        SysDept dept = sysDeptMapper.selectByPrimaryKey(id);

        if (dept == null){
            throw new GlobalException(BaseResponseCode.DATA_ERROR);
        }
        //拿到当前要删除节点的叶子节点
        List<String> list = sysDeptMapper.selectChildIds(dept.getRelationCode());

        //判断他和他的子集的叶子节点是否关联用户
        List<SysUser> sysUsers = userService.selectUserInfoByDeptIds(list);

        if (!sysUsers.isEmpty()){
            //关联用户就不能删除
            throw new GlobalException(BaseResponseCode.NOT_PERMISSION_DELETED_DEPT);
        }
        int i = sysDeptMapper.deletedDepts(new Date(), list);
        if (i < 1){
            throw new GlobalException(BaseResponseCode.OPERATION_ERROR);
        }

    }
}
